<?php
/** Clasa de suport pentru autorizarea utilizatorilor;
 * @package AMFramework
 * @subpackage Security_Pack
 * @author Marcu Alexandru
 * @version 1.0 $Build 305b  
 */
defined('_INDEX') or die('Restricted');

define('CAN_READ',1); //0001
define('CAN_EDIT',3); //0011
define('CAN_CREATE',7); // 0111
define('CAN_DELETE',15); //1111

class Amfw_Authorization {
	// Sursa de stocare a regulilor de autorizare(`permission masks`)
	// Unica pentru fiecare aplicatie finala;
	private $_authMaskTable = '';
	private $_authMaskIdCol = ''; 
	private $_authLevelCol = '';
	private $_authGroupCol = '';
	
	// Informatii despre sursa de stocare a informatiilor ce trebuiesc autorizate
	// Unica pentru fiecare instanta a obiectului, dar pot exista oricate instante
	private $_contentTable = '';
	private $_contentAccessCol = '';
	private $_contentPrimaryId = '';
	
	//Obiect static initializat la inceputul aplicatiei cu informatiile din baza de date
	private static $permissionSource = array();	
	// Container pentru instantele obiectului
	private static $instances = array();
	
	// Mai multe instante pentru surse de continut diferite;
	// Initializeaza sursa de permisii in mod static
	static function initialize($permissionSource) {
		self::$permissionSource = $permissionSource;
	}
	
	// Da instanta obiectului de autorizare corespunzator sursei de continut specificate
	// Prima data trebuie specificate toate argumentele pentru a putea fi creata instanta (deci de recomandat mereu)
	static function getInstance($contentSource, $primaryId = null, $accessCol = null) {
		if(!isset(self::$instances[$contentSource])&&isset($primaryId)&&isset($accessCol)) {
			self::$instances[$contentSource] = self::_createInstance($contentSource,$primaryId,$accessCol);
		} elseif(!isset(self::$instances[$contentSource])) {
			Amfw_Debug::toJournal("Could not create AuthZ Instance for $contentSource");
			return null;
		} 
		return self::$instances[$contentSource];
	}
	// Creaza instanta obiectului de autorizare cu sursa de continut specificata
	static function _createInstance($contentSource, $primaryId, $accessCol) {
		$instance = new Amfw_Authorization($contentSource, $primaryId, $accessCol);
		return $instance;
	}
	
	function __construct($contentSource, $primaryId, $accessCol) {
		$this->_contentTable = $contentSource;
		$this->_contentPrimaryId = $primaryId;
		$this->_contentAccessCol = $accessCol;
		
		$permissionSource = self::$permissionSource;
		if(!is_array($permissionSource)) 
			$permissionSource = (Array) $permissionSource;
		
		foreach($permissionSource as $key => $value) {
			$this->$key = $value;
		}
	}
	
	
	// Economiseste un query, adaugand la query-ul curent informatiile despre autorizare
	function authorizeSqlBool($permission, $userGroupId) {
		if(is_string($permission)) {
			$permission = bindec($permission);
		}
		// permission should be customizable in binary 1111
		//(SELECT acl FROM pmasks WHERE gid ='7' AND ID_mask = `xfii_articles`.access) > needed_permission
		$sql = "(SELECT $this->_authLevelCol FROM $this->_authMaskTable ";
		$sql .= "WHERE $this->_authGroupCol = '$userGroupId' AND ";
		$sql .= "$this->_authMaskIdCol = `$this->_contentTable`.$this->_contentAccessCol) ";
		$sql .= ">= $permission"; 
		
		return $sql;
	}
	
	//Autorizeaza un anumit ID din sursa de continut si intoarce rezultatul
	function authorizeItem($permission, $itemId, $userGroupId, $dbo = null) {
		if(!isset($dbo)) {
			$dbo =& Amfw_Factory::getDb();
		}		
		$authSql = $this->authorizeSqlBool($permission,$userGroupId);
		$dbo->setQuery("SELECT $authSql FROM $this->_contentTable WHERE $this->_contentPrimaryId = '$itemId' LIMIT 1",true);
		$result = $dbo->getResult();
		$result = ($result == '1') ? true : false;
		return $result;
	}

	//Ia lista de autorizare a intregului tabel sau  doar a unui singur element daca itemID este specificat
	function getACL($gid, $itemId = null, $dbo = null, $binary = false) {
		//SELECT ID_article,(SELECT acl FROM pmasks WHERE gid ='7' AND ID_mask = `xfii_articles`.access) as ACL FROM xfii_articles
		// WHERE ID_article = '$itemID';
		if(!isset($dbo)) {
			$dbo =& Amfw_Factory::getDb();
		}
		$sql = "SELECT $this->_contentPrimaryId, ";
		$sql .= "(SELECT $this->_authLevelCol FROM $this->_authMaskTable ";
		$sql .= "WHERE $this->_authGroupCol = '$gid' AND ";
		$sql .= "$this->_authMaskIdCol = `$this->_contentTable`.$this->_contentAccessCol) AS Acl ";
		$sql .= "FROM $this->_contentTable";
		if(!empty($itemId)) {
			$sql .= " WHERE $this->_contentPrimaryId = '$itemId'";
		}
		$dbo->setQuery($sql);
		$dbo->query();
		$rowList = $dbo->getRowList();
		$aclList = array();
		foreach($rowList as $row) {
			$aclList[$row[0]] = $binary ? decbin($row[1]) : $row[1];
		}
		//var_dump($aclList);
		//die();
		return $aclList;
	}
}